package com.gitee.jjnnzb.designpatterninspring.common.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.spec.RSAPublicKeySpec;

/**
 * <a href="https://www.cnblogs.com/felordcn/p/12142528.html">手把手教你实现JWT Token</a>
 *
 * @author Jjn
 * @since 2021-11-09 11:17
 */
@Configuration
public class JksConfig {
    
    private KeyStore store;
    
    private final Object lock = new Object();
    
    @Bean
    public KeyPair init() {
        return create("jwt.jks", "jwtkey", "Demo@2023");
    }
    
    /**
     * 获取公私钥.
     * keytool -genkeypair -alias jwtkey -keyalg RSA -keysize 2048 -keystore jwt.jks -storepass Demo@2023
     *
     * @param keyPath  jks 文件在 resources 下的classpath
     * @param keyAlias keytool 生成的 -alias 值  felordcn
     * @param keyPass  keytool 生成的  -storepass 值  123456
     * @return the key pair 公私钥对
     */
    KeyPair create(String keyPath, String keyAlias, String keyPass) {
        ClassPathResource resource = new ClassPathResource(keyPath);
        char[] pem = keyPass.toCharArray();
        try {
            synchronized (lock) {
                if (store == null) {
                    synchronized (lock) {
                        store = KeyStore.getInstance("jks");
                        store.load(resource.getInputStream(), pem);
                    }
                }
            }
            RSAPrivateCrtKey key = (RSAPrivateCrtKey) store.getKey(keyAlias, pem);
            RSAPublicKeySpec spec = new RSAPublicKeySpec(key.getModulus(), key.getPublicExponent());
            PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(spec);
            return new KeyPair(publicKey, key);
        } catch (Exception e) {
            throw new IllegalStateException("Cannot load keys from store: " + resource, e);
        }
        
    }
}
